package com.ruoyi.project.activiti.controller;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.github.pagehelper.PageHelper;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.project.activiti.domain.ActReModel;
import com.ruoyi.project.activiti.service.IActReModelService;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.function.Predicate;

/**
 * 模型管理
 */
@Controller
@RequestMapping("act/models")
public class ModelerController extends BaseController {
    @Autowired
    RepositoryService repositoryService;

    @Autowired
    ObjectMapper objectMapper;

    @Autowired
    private IActReModelService modelService;

    /**
     * 新建一个空模型
     *
     * @return
     * @throws UnsupportedEncodingException
     */
    @GetMapping("newModel")
    @ResponseBody
    public AjaxResult newModel(String name,String description,String key) throws UnsupportedEncodingException {
        // 检测该模型是否添加过
        List<ActReModel> actReModels = modelService.selectActReModelList(null);
        boolean isNameExist = actReModels.stream().anyMatch(model -> model.getName().equals(name));
        boolean isKeyExist = actReModels.stream().anyMatch(model -> model.getKey().equals(key));
        AjaxResult result;
        if(isNameExist){
            result = AjaxResult.error("该流程名称已存在");
        }else if(isKeyExist){
            result = AjaxResult.error("该流程定义Key已存在");
        }else {
            // 初始化一个空模型
            Model model = repositoryService.newModel();
            // 设置一些默认信息
            int revision = 1;
            ObjectNode modelNode = objectMapper.createObjectNode();
            modelNode.put(ModelDataJsonConstants.MODEL_NAME, name);
            modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
            modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision);
            model.setName(name);
            model.setKey(key);
            model.setMetaInfo(modelNode.toString());
            repositoryService.saveModel(model);
            // 完善ModelEditorSource
            ObjectNode editorNode = objectMapper.createObjectNode();
            editorNode.put("id", "canvas");
            editorNode.put("resourceId", "canvas");
            ObjectNode stencilSetNode = objectMapper.createObjectNode();
            stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
            editorNode.replace("stencilset", stencilSetNode);
            repositoryService.addModelEditorSource(model.getId(), editorNode.toString().getBytes("utf-8"));
            result = AjaxResult.success("模型添加成功", model.getId());
        }
        return result;
    }

    @GetMapping("editModel/{modelId}")
    public Object newModel(@PathVariable String modelId) {
        return "redirect:/modeler.html?modelId=" + modelId;
    }

    /**
     * 发布模型为流程定义
     *
     * @param id
     * @return
     * @throws Exception
     */
    @PostMapping("deploy/{id}")
    @ResponseBody
    public AjaxResult deploy(@PathVariable("id") String id) throws Exception {
        // 获取模型
        Model modelData = repositoryService.getModel(id);
        byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());
        if (bytes == null) {
            return AjaxResult.error("模型数据为空，请先设计流程并成功保存，再进行发布。");
        }
        JsonNode modelNode = new ObjectMapper().readTree(bytes);
        BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
        if (model.getProcesses().size() == 0) {
            return AjaxResult.error("数据模型不符要求，请至少设计一条主线流程。");
        }
        byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);
        // 发布流程
        String processName = modelData.getName() + ".bpmn20.xml";
        Deployment deployment = repositoryService.createDeployment().name(modelData.getName())
                .addString(processName, new String(bpmnBytes, "UTF-8")).deploy();
        modelData.setDeploymentId(deployment.getId());
        repositoryService.saveModel(modelData);
        return AjaxResult.success();
    }


    @GetMapping("get/{id}")
    public AjaxResult get(@PathVariable("id") String id) {
        Model model = repositoryService.createModelQuery().modelId(id).singleResult();
        return AjaxResult.success(model);
    }

    @GetMapping("list")
    @ResponseBody
    public TableDataInfo getList(ActReModel actReModel) {
        startPage();
        PageHelper.orderBy("create_time_ desc");
        return getDataTable(modelService.selectActReModelList(actReModel));
    }

    @PostMapping("remove")
    @ResponseBody
    public AjaxResult deleteOne(@RequestBody String[] ids) {
//        String[] idsArr = ids.split(",");
        for (String id : ids) {
            repositoryService.deleteModel(id);
        }
        return AjaxResult.success();
    }
}
